1   /*
2    * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.
8    *
9    * This code is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12   * version 2 for more details (a copy is included in the LICENSE file that
13   * accompanied this code).
14   *
15   * You should have received a copy of the GNU General Public License version
16   * 2 along with this work; if not, write to the Free Software Foundation,
17   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18   *
19   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20   * or visit www.oracle.com if you need additional information or have any
21   * questions.
22   */
23  
24  /*
25   * @test
26   * @bug 4924664
27   * @summary Tests the use of the "jmx.remote.x.password.file" and
28   *          "jmx.remote.x.access.file" environment map properties.
29   * @author Luis-Miguel Alventosa
30   * @run clean PasswordAccessFileTest SimpleStandard SimpleStandardMBean
31   * @run build PasswordAccessFileTest SimpleStandard SimpleStandardMBean
32   * @run main PasswordAccessFileTest
33   */
34  
35  import java.io.File;
36  import java.util.HashMap;
37  import javax.management.Attribute;
38  import javax.management.MBeanServer;
39  import javax.management.MBeanServerConnection;
40  import javax.management.MBeanServerFactory;
41  import javax.management.MBeanServerInvocationHandler;
42  import javax.management.Notification;
43  import javax.management.NotificationListener;
44  import javax.management.ObjectName;
45  import javax.management.remote.JMXConnector;
46  import javax.management.remote.JMXConnectorFactory;
47  import javax.management.remote.JMXConnectorServer;
48  import javax.management.remote.JMXConnectorServerFactory;
49  import javax.management.remote.JMXServiceURL;
50  
51  public class PasswordAccessFileTest {
52  
53      public static void main(String[] args) {
54          try {
55              //------------------------------------------------------------------
56              // SERVER
57              //------------------------------------------------------------------
58  
59              // Instantiate the MBean server
60              //
61              System.out.println("Create the MBean server");
62              MBeanServer mbs = MBeanServerFactory.createMBeanServer();
63  
64              // Create SimpleStandard MBean
65              //
66              ObjectName mbeanName = new ObjectName("MBeans:type=SimpleStandard");
67              System.out.println("Create SimpleStandard MBean...");
68              mbs.createMBean("SimpleStandard", mbeanName, null, null);
69  
70              // Server's environment map
71              //
72              System.out.println(">>> Initialize the server's environment map");
73              HashMap sEnv = new HashMap();
74  
75              // Provide the password file used by the connector server to
76              // perform user authentication. The password file is a properties
77              // based text file specifying username/password pairs. This
78              // properties based password authenticator has been implemented
79              // using the JMXAuthenticator interface and is passed to the
80              // connector through the "jmx.remote.authenticator" property
81              // in the map.
82              //
83              // This property is implementation-dependent and might not be
84              // supported by all implementations of the JMX Remote API.
85              //
86              sEnv.put("jmx.remote.x.password.file",
87                       System.getProperty("test.src") +
88                       File.separator +
89                       "password.properties");
90  
91              // Provide the access level file used by the connector server to
92              // perform user authorization. The access level file is a properties
93              // based text file specifying username/access level pairs where
94              // access level is either "readonly" or "readwrite" access to the
95              // MBeanServer operations. This properties based access control
96              // checker has been implemented using the MBeanServerForwarder
97              // interface which wraps the real MBean server inside an access
98              // controller MBean server which performs the access control checks
99              // before forwarding the requests to the real MBean server.
100             //
101             // This property is implementation-dependent and might not be
102             // supported by all implementations of the JMX Remote API.
103             //
104             sEnv.put("jmx.remote.x.access.file",
105                      System.getProperty("test.src") +
106                      File.separator +
107                      "access.properties");
108 
109             // Create an RMI connector server
110             //
111             System.out.println("Create an RMI connector server");
112             JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
113             JMXConnectorServer cs =
114                 JMXConnectorServerFactory.newJMXConnectorServer(url, sEnv, mbs);
115 
116             // Start the RMI connector server
117             //
118             System.out.println("Start the RMI connector server");
119             cs.start();
120             System.out.println("RMI connector server successfully started");
121             System.out.println("Waiting for incoming connections...");
122 
123             //------------------------------------------------------------------
124             // CLIENT : Invalid authentication credentials
125             //------------------------------------------------------------------
126 
127             final String invalidCreds[][] = {
128                 {"admin1", "adminPassword"},
129                 {"admin",  "adminPassword1"},
130                 {"user1",  "userPassword"},
131                 {"user",   "userPassword1"}
132             };
133 
134             // Try to connect to the server using the invalid credentials.
135             // All the connect calls should get SecurityException.
136             //
137             for (int i = 0 ; i < invalidCreds.length ; i++) {
138                 // Client environment map
139                 //
140                 System.out.println(">>> Initialize the client environment map" +
141                                    " for user [" +
142                                    invalidCreds[i][0] +
143                                    "] with password [" +
144                                    invalidCreds[i][1] + "]");
145                 HashMap cEnv = new HashMap();
146                 cEnv.put("jmx.remote.credentials", invalidCreds[i]);
147 
148                 // Create an RMI connector client and
149                 // connect it to the RMI connector server
150                 //
151                 System.out.println("Create an RMI connector client and " +
152                                    "connect it to the RMI connector server");
153                 try {
154                     JMXConnector jmxc =
155                         JMXConnectorFactory.connect(cs.getAddress(), cEnv);
156                 } catch (SecurityException e) {
157                     System.out.println("Got expected security exception: " + e);
158                 } catch (Exception e) {
159                     System.out.println("Got unexpected exception: " + e);
160                     e.printStackTrace();
161                     System.exit(1);
162                 }
163             }
164 
165             //------------------------------------------------------------------
166             // CLIENT (admin)
167             //------------------------------------------------------------------
168 
169             // Admin client environment map
170             //
171             String[] adminCreds = new String[] { "admin" , "adminPassword" };
172             System.out.println(">>> Initialize the client environment map for" +
173                                " user [" + adminCreds[0] + "] with " +
174                                "password [" + adminCreds[1] + "]");
175             HashMap adminEnv = new HashMap();
176             adminEnv.put("jmx.remote.credentials", adminCreds);
177 
178             // Create an RMI connector client and
179             // connect it to the RMI connector server
180             //
181             System.out.println("Create an RMI connector client and " +
182                                "connect it to the RMI connector server");
183             JMXConnector adminConnector =
184                 JMXConnectorFactory.connect(cs.getAddress(), adminEnv);
185 
186             // Get an MBeanServerConnection
187             //
188             System.out.println("Get an MBeanServerConnection");
189             MBeanServerConnection adminConnection =
190                 adminConnector.getMBeanServerConnection();
191 
192             // Get the proxy for the Simple MBean
193             //
194             SimpleStandardMBean adminProxy = (SimpleStandardMBean)
195                 MBeanServerInvocationHandler.newProxyInstance(
196                                              adminConnection,
197                                              mbeanName,
198                                              SimpleStandardMBean.class,
199                                              false);
200 
201             // Get State attribute
202             //
203             System.out.println("State = " + adminProxy.getState());
204 
205             // Set State attribute
206             //
207             adminProxy.setState("changed state");
208 
209             // Get State attribute
210             //
211             System.out.println("State = " + adminProxy.getState());
212 
213             // Invoke "reset" in SimpleStandard MBean
214             //
215             System.out.println("Invoke reset() in SimpleStandard MBean...");
216             adminProxy.reset();
217 
218             // Close MBeanServer connection
219             //
220             System.out.println("Close the admin connection to the server");
221             adminConnector.close();
222 
223             //------------------------------------------------------------------
224             // CLIENT (user)
225             //------------------------------------------------------------------
226 
227             // User client environment map
228             //
229             String[] userCreds = new String[] { "user" , "userPassword" };
230             System.out.println(">>> Initialize the client environment map for" +
231                                " user [" + userCreds[0] + "] with " +
232                                "password [" + userCreds[1] + "]");
233             HashMap userEnv = new HashMap();
234             userEnv.put("jmx.remote.credentials", userCreds);
235 
236             // Create an RMI connector client and
237             // connect it to the RMI connector server
238             //
239             System.out.println("Create an RMI connector client and " +
240                                "connect it to the RMI connector server");
241             JMXConnector userConnector =
242                 JMXConnectorFactory.connect(cs.getAddress(), userEnv);
243 
244             // Get an MBeanServerConnection
245             //
246             System.out.println("Get an MBeanServerConnection");
247             MBeanServerConnection userConnection =
248                 userConnector.getMBeanServerConnection();
249 
250             // Get the proxy for the Simple MBean
251             //
252             SimpleStandardMBean userProxy = (SimpleStandardMBean)
253                 MBeanServerInvocationHandler.newProxyInstance(
254                                              userConnection,
255                                              mbeanName,
256                                              SimpleStandardMBean.class,
257                                              false);
258 
259             // Get State attribute
260             //
261             System.out.println("State = " + userProxy.getState());
262 
263             // Set State attribute
264             //
265             try {
266                 userProxy.setState("changed state");
267             } catch (SecurityException e) {
268                 System.out.println("Got expected security exception: " + e);
269             } catch (Exception e) {
270                 System.out.println("Got unexpected exception: " + e);
271                 e.printStackTrace();
272                 System.exit(1);
273             }
274 
275             // Get State attribute
276             //
277             System.out.println("State = " + userProxy.getState());
278 
279             // Invoke "reset" in SimpleStandard MBean
280             //
281             try {
282                 System.out.println("Invoke reset() in SimpleStandard MBean...");
283                 userProxy.reset();
284             } catch (SecurityException e) {
285                 System.out.println("Got expected security exception: " + e);
286             } catch (Exception e) {
287                 System.out.println("Got unexpected exception: " + e);
288                 e.printStackTrace();
289                 System.exit(1);
290             }
291 
292             // Close MBeanServer connection
293             //
294             System.out.println("Close the user connection to the server");
295             userConnector.close();
296 
297             //------------------------------------------------------------------
298             // SERVER
299             //------------------------------------------------------------------
300 
301             // Stop the connector server
302             //
303             System.out.println(">>> Stop the connector server");
304             cs.stop();
305 
306             System.out.println("Bye! Bye!");
307         } catch (Exception e) {
308             System.out.println("Got unexpected exception: " + e);
309             e.printStackTrace();
310             System.exit(1);
311         }
312     }
313 }